﻿using GameProtocol.Protocol;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace NetCommon
{
    /// <summary>
    /// 二进制数组的读写操作
    /// </summary>
    public class ByteArray
    {
        //https://blog.csdn.net/pan_junbiao/article/details/82952613
        MemoryStream ms;
        BinaryReader br;
        BinaryWriter bw;//二进制形式写入流
        /// <summary>
        /// 构造函数——实例化字节流
        /// </summary>
        public ByteArray()
        {
            ms = new MemoryStream();
            br = new BinaryReader(ms);
            bw = new BinaryWriter(ms);
        }
        public ByteArray(byte[] buff)
        {
            ms = new MemoryStream(buff);
            br = new BinaryReader(ms);
            bw = new BinaryWriter(ms);
        }
        #region 数据写到流里面
        public void Write(Protocal value)
        {
            bw.Write((byte)value);
        }
        public void Write(byte value)
        {
            bw.Write(value);
        }
        public void Write(short value)
        {
            bw.Write(value);
        }
        public void Write(int value)
        {
            bw.Write(value);
        }
        public void Write(bool value)
        {
            bw.Write(value);
        }
        public void Write(string value)
        {
            bw.Write(value);
        }
        public void Write(byte[] value)
        {
            bw.Write(value);
        }
        public void Write(double value)
        {
            bw.Write(value);
        }
        public void Write(float value)
        {
            bw.Write(value);
        }
        public void Write(long value)
        {
            bw.Write(value);
        }
        //BinaryWrite 不支持写入 object类型的
        public void Write(object value)
        {
            MemoryStream ms = new MemoryStream();//内存流
            BinaryFormatter bf = new BinaryFormatter();//完成序列化对象的图形
            bf.Serialize(ms, value);//序列化object类型对象，存储到内存流中
            byte[] buff = new byte[ms.Length];//字节流数组
            //将 从指定偏移量 开始的 源数组中 指定数量的字节 复制到 以特定偏移量 开始的 目标数组
            Buffer.BlockCopy(ms.GetBuffer(), 0, buff, 0, (int)ms.Length);
            bw.Write(buff);//写入
            ms.Close();
        }
        #endregion

        #region 从字节流中读取数据
        public void Read(out Protocal value)
        {
            value = (Protocal)(br.ReadByte());
        }
        public void Read(out byte value)
        {
            value = br.ReadByte();
        }
        public void Read(out short value)
        {
            value = br.ReadInt16();
        }
        public void Read(out int value)
        {
            value = br.ReadInt32();
        }
        public void Read(out bool value)
        {
            value = br.ReadBoolean();
        }
        public void Read(out string value)
        {
            value = br.ReadString();
        }
        public void Read(out byte[] value, int length)
        {
            value = br.ReadBytes(length);
        }
        public void Read(out double value)
        {
            value = br.ReadDouble();
        }
        public void Read(out float value)
        {
            value = br.ReadSingle();
        }
        public void Read(out long value)
        {
            value = br.ReadInt64();
        }
        public void Read(int len, out object value)
        {
            if (!Readable)
            {//无数据可读
                value = null;
                return;
            }

            byte[] msg;
            Read(out msg, len);

            MemoryStream ms = new MemoryStream(msg);
            BinaryFormatter bf = new BinaryFormatter();

            value = bf.Deserialize(ms);
            ms.Close();
        }
        #endregion
        /// <summary>
        /// 当前流的位置
        /// </summary>
        public int Position
        {
            get { return (int)ms.Position; }
        }
        /// <summary>
        /// 当前流的长度
        /// </summary>
        public int Length
        {
            get { return (int)ms.Length; }
        }
        /// <summary>
        /// 当前流里面的数据
        /// </summary>
        public byte[] Buff
        {
            get { return ms.GetBuffer(); }
        }
        /// <summary>
        /// 是否有数据可以读取
        /// </summary>
        public bool Readable
        {
            get {
                //流的长度大于流的位置
                return Length > Position;
            }
        }
        /// <summary>
        /// 重置流位置
        /// </summary>
        public void ResetPosition()
        {
            ms.Position = 0;
        }
        public byte[] GetBuff()
        {
            byte[] buff = new byte[Length];
            Buffer.BlockCopy(ms.GetBuffer(), 0, buff, 0, Length);
            return buff;
        }
        public void Close()
        {
            ms.Close();
            br.Close();
            bw.Close();
        }
    }
}
